#lang r5rs
(define (foldr op initial result)
  (if(null? result)
     initial
     (op (car result)
         (foldr op initial (cdr result)))))

(define (filter prediction l)
  (cond ((null? l) '())
        ((prediction (car l)) (cons (car l) (filter prediction (cdr l))))
        ((not(prediction (car l))) (filter prediction (cdr l)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define (enum-pairs n m);m = number of member in pairs
  (define (enum-int n l)
    (if(= 0 n)
       l
       (enum-int (- n 1) (append (list(list n)) l))))
  (define (flatmap l)
    (foldr append
           '()
           (map (lambda (x) (map (lambda (y) (append x y)) (enum-int n '()))) l)))
  (define (nf n f)
    (define (nny m y x)
         (if(= 0 m)
            x
            (y (nny (- m 1) y x))))
    (lambda (x)
      
       (nny n f x)
       ))
  ((nf (- m 1) flatmap) (enum-int n '()))
;  (flatmap (flatmap (enum-int n '())))
  )
(define (pairs-of-sum sum n)
  (define (have-equal? x)
    (define (have-equal-iter? checklist)
      (if (null? checklist)
          #f
          (or (pair? (filter (lambda(x) (= x (car checklist))) (cdr checklist))) (have-equal-iter? (cdr checklist)))))
    (have-equal-iter? x))
  (define (sum-of? x)
    (= (foldr + 0 x) sum))
  (filter have-equal?
          (filter sum-of?
                  (enum-pairs n 3))))

;(display (enum-pairs 5 3))

(display (pairs-of-sum 11 7))
